package com.cxx.home.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.cxx.home.dto.message.MailMessageDto;
import com.cxx.home.dto.plan.PlanDto;
import com.cxx.home.dto.plan.PlanStatsDto;
import com.cxx.home.dto.task.TaskDto;
import com.cxx.home.entity.Plan;
import com.cxx.home.mapper.PlanMapper;
import com.cxx.home.vo.PlanQueryVo;
import com.cxx.home.dao.PlanDao;
import com.cxx.home.schedule.TaskType;
import com.cxx.home.service.PlanService;
import com.cxx.home.service.TaskService;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class PlanServiceImpl implements PlanService {
    @Resource
    private PlanDao planDao;

    @Resource
    private PlanMapper planMapper;

    @Resource
    private TaskService taskService;

    @Override
    public Boolean addPlan(PlanDto planDto) {
        Plan plan = new Plan();
        BeanUtils.copyProperties(planDto, plan);

        // 如果存在提醒时间，则新建定时任务
        if (planDto.getAlterTime() != null) {
            plan.setTaskId(addPlanTask(planDto));
        }

        return planMapper.insert(plan) == 1;
    }

    @Override
    public Boolean updatePlan(Long id, PlanDto planDto) {
        Plan plan = new Plan();
        BeanUtils.copyProperties(planDto, plan);
        plan.setId(id);
        planMapper.updateById(plan);

        // 如果存在定时任务，则更新
        if (planDto.getTaskId() != null) {
            updatePlanTask(id, plan.getTaskId(), planDto);
        } else {
            // 如果不存在定时任务，但存在提醒时间，则新建
            if (planDto.getAlterTime() != null) {
                plan.setTaskId(addPlanTask(planDto));
                planMapper.updateById(plan);
            }
        }

        return Boolean.TRUE;
    }

    @Override
    public Boolean deletePlan(Long id) {
        Plan plan = planMapper.selectById(id);

        // 如果存在定时任务
        if (plan != null && plan.getTaskId() != null) {
            Long taskId = plan.getTaskId();

            // 如果存在提醒时间，则删除
            if (plan.getAlterTime() != null) {
                taskService.deleteTask(taskId);
            }
        }

        return planMapper.deleteById(id) == 1;
    }

    @Override
    public List<PlanDto> queryPlan(PlanQueryVo query) {
        return planDao.queryPlan(query);
    }

    @Override
    public Boolean setPlanStatus(Long id, Boolean status) {
        UpdateWrapper<Plan> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id).set("completed", status ? 1 : 0);

        return planMapper.update(null, updateWrapper) > 0;
    }

    @Override
    public PlanStatsDto queryPlanStats() {
        return planDao.queryPlanStats();
    }

    private Long addPlanTask(PlanDto planDto) {
        TaskDto taskDto = new TaskDto();
        taskDto.setType(TaskType.EMAIL);
        taskDto.setContent(getPlanContent(planDto));
        taskDto.setExecuteTime(planDto.getAlterTime());
        return taskService.addTask(taskDto);
    }

    private void updatePlanTask(Long planId, Long taskId, PlanDto planDto) {
        TaskDto taskDto = taskService.queryTaskById(taskId);

        // 如果存在提醒时间，则更新
        if (planDto.getAlterTime() != null) {
            taskDto.setContent(getPlanContent(planDto));
            taskDto.setExecuteTime(planDto.getAlterTime());
            taskService.updateTask(taskId, taskDto);
        } else {
            // 如果不存在，则删除
            LambdaUpdateWrapper<Plan> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Plan::getId, planId).set(Plan::getTaskId, null);
            planMapper.update(updateWrapper);
            taskService.deleteTask(taskId);
        }
    }

    private String getPlanContent(PlanDto planDto) {
        MailMessageDto messageDto = new MailMessageDto();
        messageDto.setTo(planDto.getEmail());
        messageDto.setSubject("日程提醒");
        messageDto.setBody("<h2>" + planDto.getTitle() + "</h2><br><p>" + planDto.getContent() + "</p>");

        return JSONUtil.toJsonStr(messageDto);
    }
}
